home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / md-68k / cpuopti next >
Text File  |  1998-01-20  |  10KB  |  287 lines

  1. #!/bin/perl
  2. #
  3. # Usage: $0 <cpu?.s
  4. #
  5. # Small perl script to optimise cpu?.s
  6. # Note: some optimisations done here are not safe! It is a chance
  7. # if everything works fine...
  8. #
  9. # 05/04/97: Modified to make it work with perl5.
  10. # 25/10/97: Removed some optimisations suspected to introduce bugs.
  11. #
  12. # (c) By Samuel Devulder, 04/97.
  13. #
  14.  
  15. # uncomment the next 2 lines if you experience problems with the
  16. # optimized code:
  17. #while(<>) { print; }
  18. #exit 0;
  19.  
  20. ###############################################################################
  21.  
  22. if($#ARGV >= $[) {
  23.     &usage;
  24.  
  25. ###############################################################################
  26.  
  27. while(<>) {
  28.     print;
  29.     last if /^_op_[0-9a-f]+:$/;
  30. }
  31.  
  32. ###############################################################################
  33.  
  34. chop;
  35. print STDERR "$_\r";
  36. $num_opt = 0;
  37. while($last_func = &analyse_function) {
  38.     while(&optimize_function) {}
  39.     &dump_function;
  40.     print $last_func;$_ = $last_func;chop;
  41.     print STDERR "$_\r";
  42. }
  43. while(&optimize_function) {}
  44. &dump_function;
  45.  
  46. print STDERR "$num_opt optimisations\n";
  47.  
  48. exit 0;
  49.  
  50. ###############################################################################
  51.  
  52. sub delete_line {
  53.     local($i) = @_;
  54.     for(; $i < $lineno; ++$i) {
  55.         $line[$i] = $line[1+$i];
  56.     }
  57.     $line[--$lineno] = "";
  58. }
  59.     
  60. ###############################################################################
  61.  
  62. sub optimize_function {
  63.     local($i, $j, $ext, $adr, $reg, $opt, $tmp);
  64.     $opt = $num_opt;
  65.     for($i = 0; $i < $lineno; ++$i) {
  66.         study($line[$i]);
  67.         #################################################################
  68.         #   INST.x  X,Dn            =>  INST.x  X,Dn
  69.         #   TST.x   Dn                  <deleted>
  70.         #################################################################
  71.         if(($line[$i] =~/(mov[e]?|or|and|add|sub|tst)([bwl])\s+.+,(d[0-7])$/)
  72.         && ($line[$i+1]=~ /tst$2\s+$3/)) {
  73.             &delete_line($i+1);
  74.             ++$num_opt;
  75.         } 
  76.         #################################################################
  77.         #   MOVE.x  Dn,X            =>  MOVE.x  Dn,X
  78.         #   TST.x   Dn                  <deleted>
  79.         #################################################################
  80.         if(($line[$i]  =~ /mov[e]?([bwl])\s+(d[0-7]),(.+)$/)
  81.         && ($line[$i+1]=~ /tst$1\s+$2/)) {
  82.             &delete_line($i+1);
  83.             ++$num_opt;
  84.         }
  85.         #################################################################
  86.         #   MOVE.B  1(An),Dr        =>  MOVE.W  (An)+,Dr
  87.         #   ADDQ.x  #2,AN               <deleted>
  88.         # This is allowed since An always points on (B1,B2) With B1==0
  89.         #################################################################
  90.         if($line[$i]   =~ /moveb\s+(a[0-7])@\(1\),(d[0-7])$/) {
  91.             $adr=$1; $reg=$2;
  92.             if($line[$i+1] =~ /addq.\s+#2,$adr/) {
  93.                 $line[$i] = "\tmovew $adr@+,$reg\n";
  94.                 &delete_line($i+1);
  95.                 ++$num_opt;
  96.         #################################################################
  97.         #   CLR.W   Dn              =>  <deleted>
  98.         #   MOVE.W  X,Dn                MOVE.W  X,Dn
  99.         #################################################################
  100.                 if(($i>1) && ($line[$i-1] =~ /clrw\s+$reg/)) {
  101.                 &delete_line($i-1);
  102.                 ++$num_opt;
  103.             }
  104.         }       
  105.         }       
  106.         #################################################################
  107.         #   TST.x   Dn              =>  MOVE.x  Dn,X
  108.         #   ..(Dn not used)..           ..(Dn not used)..
  109.         #   MOVE.x  Dn,X                <deleted>
  110.         #################################################################
  111. #        if(($line[$i] =~ /tst([bwl])\s+(d[0-7])$/)) {
  112. #            $ext = $1; $reg = $2;
  113. #            $line[$lineno] = "rts"; # sentinel
  114. #            $tmp = "(^.+:)|rts|\sj.+\s|$reg";
  115. #            for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
  116. #            if($line[$j] =~ /mov[e]?$ext\s+$reg,(.+)$/) {
  117. #                $adr = $1;
  118. #                $tmp = "";
  119. #                if($adr =~ /(a[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
  120. #                if($adr =~ /(d[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
  121. #                if(!($tmp eq "")) {
  122. #                    for($k = $i+1; $k<$j && ($line[$k]!~/$tmp/); ++$k) {}
  123. #                } else {$k = $j;}
  124. #                if($k == $j) {
  125. #                    $line[$i] = $line[$j];
  126. #                    &delete_line($j);
  127. #                    ++$num_opt;
  128. #                }
  129. #            }
  130. #        }
  131.         if($line[$i] =~ /_regs/) { # some speedup
  132.         #################################################################
  133.         #   INST   .._regs+N1..     =>  lea     _regs+N2,An
  134.         #   ..(no refs to _regs)..      INST    ..N1-N2(An)..
  135.         #   lea     _regs+N2,An         ..(no refs to _regs)..
  136.         #################################################################
  137.         if($line[$i] =~ /_regs(\+\d+)?/) {
  138.             $N1 = $1;
  139.             $line[$lineno] = "rts"; # sentinel
  140.             $tmp = "_regs|rts|\s+j.+\s|(^.+:)";
  141.             for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
  142.             if($line[$j] =~ /lea\s+_regs(\+\d+)?,(a[0-7])$/) {
  143.                 $N2 = $1; $An = $2;
  144.                 for($k = $i; $line[$k] !~ /$An/; $k++) {}
  145.                 if($k == $j) {
  146.                     $N1 =~ s/^\+//; $N2 =~ y/+/-/;
  147.                     $line[$i] =~ s/_regs(\+?)$N1/$An@\($N1$N2\)/g;
  148.                     $ext = $line[$j];
  149.                     for($k=$j; $k>$i; --$k) {$line[$k] = $line[$k-1];}
  150.                     $line[$i] = $ext;
  151.                     ++$num_opt;
  152.                 }
  153.             }
  154.         }
  155.         #################################################################
  156.         #   LEA     _regs+N1,An     =>  LEA     _regs+N1,An
  157.         #   ..An not modified..         ...
  158.         #   INST    .._regs+N2..        INST    ..(N2-N1)An..
  159.         #################################################################
  160.         if($line[$i] =~ /lea\s+_regs(\+\d+)?,(a[0-7])/) {
  161.             $N1 = $1;$An = $2;
  162.             $line[$lineno] = "rts"; # sentinel
  163.             $tmp = "_regs|$An@[-+]|,$An|\sj.+\s|rts|(^.+:)";
  164.             for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
  165.             if($line[$j] =~ /_regs(\+\d+)?/) {
  166.                 $N2 = $1; $N1 =~ y/+/-/;
  167.                 $tmp = $N2; $tmp =~ s/[+]/\\+/;
  168.                 $line[$j] =~ s/_regs$tmp/$An@\($N2$N1\)/g;
  169.                 $line[$j] =~ s/\(\)//g;
  170.                 ++$num_opt;
  171.             }
  172.         }
  173.         }
  174.         #################################################################
  175.         #   MOVE.x  X,Dp            =>  MOVE.x  X,Dp
  176.         #   ..Dp not used..             MOVE.W  CCR,Y
  177.         #   TST.x   Dp                  ..Dp not used..
  178.         #   MOVE.W  ccr,Y
  179.         #################################################################
  180. #        if($line[$i] =~ /mov[e]?([bwl])\s+.+,(d[0-7])$/) {
  181. #            $ext = $1;$reg = $2;
  182. #            $line[$lineno] = "rts"; # sentinel
  183. #            $tmp = "$reg|rts|\sj.+\s|(^.+:)";
  184. #            for($j = $i+1; $line[$j] !~ /$tmp/; $j++) {}
  185. #            if(($line[$j] =~ /tst$ext\s+$reg$/)
  186. #            && ($line[$j+1] =~ /mov[e]?w\s+ccr,/)) {
  187. #                &delete_line($j);
  188. #                $ext = $line[$j];
  189. #                for($k=$j;$k>$i+1;--$k) {$line[$k] = $line[$k-1];}
  190. #                $line[$i+1] = $ext;
  191. #                ++$num_opt;
  192. #            }
  193. #        }
  194.         #################################################################
  195.         # General instruction scheduling optimisation:
  196.         #   INST1   <memory op>     =>  INST1   <memory op>
  197.         #   INST2   <memory op>         INST3   [R1,]R2
  198.         #   INST3   [R1,]R2             INST2   <memory op>
  199.         #################################################################
  200.         if(($i>=2)
  201.         && ($line[$i] =~ /\s+(([ad][0-7]),)?([ad][0-7])$/)
  202.         && ($line[$i] !~ /^.+:/)
  203.         && ($line[$i+1] !~ /ccr|jb[^s]/)) {
  204.             $adr = $2?$2:"a8"; # unused register
  205.             $reg = $3;
  206.             study($line[$i-1]);
  207.             study($line[$i-2]);
  208.             if(($line[$i-1] =~ /@|_regflags/)
  209.             && ($line[$i-2] =~ /@|_regflags/)
  210.             && ($line[$i-1] !~ /(^[^\s]+:)|$adr|$reg|jb|ccr|lea|pea/)
  211.             && ($line[$i-2] !~ /$adr|$reg|lea|pea/)) {
  212.                 $tmp        = $line[$i-1];
  213.                 $line[$i-1] = $line[$i];
  214.                 $line[$i]   = $tmp;
  215.                 ++$num_opt;
  216.             }
  217.         }
  218.     }
  219.     return $num_opt-$opt;
  220. }
  221.  
  222. ###############################################################################
  223.  
  224. sub not_used {
  225.     local($i, $reg) = @_;
  226.  
  227.     while($i < $lineno) {
  228.         $line[$i]=~/$reg/ && return 0;
  229.         ++$i;
  230.     }
  231.     return 1;
  232. }
  233.  
  234. ###############################################################################
  235.  
  236. sub not_used_before {
  237.     local($i, $reg) = @_;
  238.  
  239.     while($i--) {
  240.         $line[$i]=~/$reg/ && return 0;
  241.     }
  242.     return 1;
  243. }
  244.  
  245. ###############################################################################
  246.  
  247. sub analyse_function {
  248.     $lineno = 0;
  249.     while(<>) {
  250.         next if /^#(NO_)?APP/;
  251.         last if /^_op_[0-9a-f]+:$/;
  252.         $line[$lineno++] = $_;
  253.     }
  254.     return $_;
  255. }
  256.  
  257. ###############################################################################
  258.  
  259. sub dump_function {
  260.     local($i);
  261.     for($i=0;$i < $lineno; ++$i) {
  262.     $_ = $line[$i];
  263.     s/lea\s(a[0-7])\@\(\),/movel $1,/;
  264.         print;
  265.     }
  266. }
  267.  
  268. ###############################################################################
  269.  
  270. sub usage {
  271.     open(FILE,__FILE__);
  272.     open(OUT,"|less");
  273.     <FILE>;
  274.     while(<FILE>) {
  275.         last if !/^#/;
  276.         s/^#[ ]?//;
  277.         s/\$0/$0/;
  278.         print OUT;
  279.     }
  280.     close OUT;
  281.     exit;
  282. }
  283.     
  284. ###############################################################################
  285.     
  286.